/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.xuexiang.xui_lib.component.edittext;

import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.agp.window.dialog.PopupDialog;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.component.edittext.materialedittext.validation.METValidator;
import com.xuexiang.xui_lib.component.edittext.materialedittext.validation.TextUtils;
import com.xuexiang.xui_lib.util.ElementHelper;

import java.util.ArrayList;
import java.util.List;

/**
 * ValidatorEditText
 *
 * @since 2021-03-24
 */
public class ValidatorEditText extends ComponentContainer {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MaterialEditTextInfo");
    private static final int THREEZERO = 30;
    private static final int ONEFOUR = 14;
    private static final int FIVEZEROZERO = 500;
    private static final int EIGHTZERO = 80;
    private static final int ONEFIVE = 15;
    private static final int THREE = 3;
    private static final int TWOZERO = 20;

    private TextField input;
    private Image image;
//    private Text messText;
    private String errorMsg;
    private Paint paint;
    private Point bottomLinePointStart;
    private Point bottomLinePointEnd;
    private List<METValidator> validators = new ArrayList<>();
    private boolean isAutoValidate;
    private boolean isValid;
    private Component parentComponent;

    /**
     * 构造函数
     *
     * @param context
     */
    public ValidatorEditText(Context context) {
        super(context);
        init();
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrSet
     */
    public ValidatorEditText(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init();
    }

    /**
     * 构造函数
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public ValidatorEditText(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
    }

    private void init() {
        parentComponent = LayoutScatter.getInstance(getContext()).
            parse(ResourceTable.Layout_validator_editext, null, false);
        input = (TextField) parentComponent.findComponentById(ResourceTable.Id_validator_editext_input);
        image = (Image) parentComponent.findComponentById(ResourceTable.Id_validator_editext_image);
        input.setPaddingRight(AttrHelper.vp2px(THREEZERO, getContext()));
        DependentLayout.LayoutConfig layoutConfig = new DependentLayout.LayoutConfig();
        layoutConfig.addRule(DependentLayout.LayoutConfig.ALIGN_PARENT_RIGHT, ResourceTable.Id_validator_editext_input);
        layoutConfig.addRule(DependentLayout.LayoutConfig.VERTICAL_CENTER);
        image.setLayoutConfig(layoutConfig);
        paint = new Paint();
        paint.setAntiAlias(true);
        addComponent(parentComponent); // 添加layout到父组件
        addDrawTask(new DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                drawBorder(canvas);
            }
        });
        setUpView();
    }

    private void setUpView() {
        input.setFocusChangedListener(new FocusChangedListener() {
            @Override
            public void onFocusChange(Component component, boolean isB) {
                invalidate();
            }
        });
        input.addTextObserver(new Text.TextObserver() {
            @Override
            public void onTextUpdated(String s, int i, int i1, int i2) {
                if (isAutoValidate) {
                    validate();
                } else {
                    resetMessText();
                }
            }
        });
        image.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (TextUtils.isEmpty(errorMsg)) {
                    return;
                }
                showMsgPup();
            }
        });
    }

    private void showMsgPup() {
        Component component = LayoutScatter.getInstance(getContext()).
            parse(ResourceTable.Layout_validator_popu, null, false);
        Text text = (Text) component.findComponentById(ResourceTable.Id_validator_popu_messege);
        text.setTextColor(Color.WHITE);
        text.setTextSize(AttrHelper.fp2px(ONEFOUR, getContext()));
        text.setText(errorMsg);
        PopupDialog popupDialog = new PopupDialog(getContext(), input);
        popupDialog.setSize(FIVEZEROZERO, EIGHTZERO);
        popupDialog.setMode(LayoutAlignment.TOP);
        popupDialog.setCustomComponent(component);
        popupDialog.setHasArrow(true);
        popupDialog.setArrowSize(THREEZERO, ONEFIVE);
        popupDialog.setTransparent(true);
        popupDialog.setAutoClosable(true);
        popupDialog.setBackColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
        popupDialog.show();
    }

    /**
     * 能否输入
     *
     * @param isEnable
     */
    public void setInputEnable(Boolean isEnable) {
        input.setEnabled(isEnable);
        input.setTouchFocusable(isEnable);
        input.setFocusable(isEnable ? Component.FOCUS_ENABLE : Component.FOCUS_DISABLE);
    }

    public void setAutoValidate(boolean isAutoValidate1) {
        this.isAutoValidate = isAutoValidate1;
    }

    public boolean isEnabled() {
        return input.isEnabled();
    }

    private void setImageVisibility(int visibility) {
        image.setVisibility(visibility);
    }

    /**
     * addValidator
     *
     * @param validator
     */
    public void addValidator(METValidator validator) {
        if (validators == null) {
            this.validators = new ArrayList<>();
        }
        this.validators.add(validator);
        if (TextUtils.isEmpty(errorMsg)) {
            errorMsg = validator.getErrorMessage();
        }
    }

    public String getText() {
        return input.getText();
    }

    public boolean getValid() {
        return isValid;
    }

    /**
     * validate
     *
     * @return boolean
     */
    public boolean validate() {
        if (validators == null || validators.isEmpty()) {
            return true;
        }
        CharSequence text = getText();
        boolean isEmpty = TextUtils.isEmpty(text);

        isValid = true;
        for (METValidator validator : validators) {
            isValid = isValid && validator.isValid(text, isEmpty);
            if (!isValid) {
                errorMsg = validator.getErrorMessage();
                setImageVisibility(Component.VISIBLE);
                invalidate();
                break;
            }
        }
        if (isValid) {
            resetMessText();
        }
        return isValid;
    }

    private void resetMessText() {
        setImageVisibility(Component.HIDE);
        invalidate();
        errorMsg = "";
    }

    private void drawBorder(Canvas canvas) {
        paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_gray_light));
        paint.setStyle(Paint.Style.STROKE_STYLE); // 空心矩形框
        paint.setStrokeWidth(THREE);
        if (!TextUtils.isEmpty(errorMsg)) {
            paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
        } else if (input.hasFocus() && !TextUtils.isEmpty(errorMsg)) {
            paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
        } else if (input.hasFocus() && TextUtils.isEmpty(errorMsg)) {
            paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_blue_light));
        } else if (!input.hasFocus()) {
            paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
        } else if (!isEnabled()) {
            paint.setStrokeWidth(1);
        }
        RectFloat oval3 = new RectFloat(
            input.getComponentPosition().left,
            input.getComponentPosition().top,
            input.getComponentPosition().right,
            input.getComponentPosition().bottom);
        canvas.drawRoundRect(oval3, TWOZERO, ONEFIVE, paint);
    }

    /**
     * 底部线条
     *
     * @param canvas
     */
    private void drawBottomline(Canvas canvas) {
        bottomLinePointStart = new Point(input.getComponentPosition().left, input.getComponentPosition().bottom);
        bottomLinePointEnd = new Point(input.getComponentPosition().right, input.getComponentPosition().bottom);
        paint.setStrokeWidth(THREE);
        if (!TextUtils.isEmpty(errorMsg)) {
            paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_red_light));
        } else if (input.hasFocus()) {
            paint.setColor(ElementHelper.getColor(getContext(), ResourceTable.Color_blue_light));
        } else if (!isEnabled()) {
            paint.setStrokeWidth(1);
            paint.setColor(Color.BLACK);
        }
        canvas.save();
        canvas.drawLine(bottomLinePointStart, bottomLinePointEnd, paint);
        canvas.restore();
    }
}
